<template>
  <!--抽取任务 -->
  <div class="general-page">
    <el-form :inline="true" v-model="searchParams" class="page-search">
      <el-form-item label="任务名称">
        <el-input
          v-model="searchParams.file_name"
          placeholder="请输入内容"
          clearable
          size="small"
          style="width: 240px"
        ></el-input>
      </el-form-item>
      <el-form-item label="抽取类型" class="extraction_model_id">
        <el-select
          v-model="searchParams.extraction_type"
          size="small"
          clearable
          placeholder="请选择抽取类型"
          style="width: 240px"
        >
          <!-- <el-option label="算法" :value="1"></el-option> -->
          <el-option label="大模型" :value="2"></el-option>
          <el-option label="正则表达式" :value="3"></el-option>
          <el-option label="结构化抽取" :value="4"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="状态" class="status">
        <el-select
          v-model="searchParams.status"
          clearable
          size="small"
          placeholder="全部"
          style="width: 240px"
        >
          <el-option
            v-for="s in statusOptions"
            :key="s.value"
            :label="s.label"
            :value="s.value"
          ></el-option>
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button
          type="primary"
          size="small"
          @click="searchData"
          style="width: 60px"
          >查询</el-button
        >
      </el-form-item>
    </el-form>
    <div class="page-table">
      <div class="table-toolbar">
        <div class="table-title">抽取任务</div>
        <div class="table-opera">
          <el-button type="primary" size="small" @click="importGraph">
            导入图谱
            <el-tooltip
              content="仅处理任务为已完成状态且抽取内容为已确认状态的数据"
            >
              <i class="el-icon-warning"></i>
            </el-tooltip>
          </el-button>
        </div>
      </div>
      <el-table
        :data="tableList"
        class="map-manage"
        v-loading="loading"
        :header-cell-style="{ background: '#F3F4F8', color: '#000000' }"
        :cell-style="{ color: '#333333' }"
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="50" align="center">
        </el-table-column>
        <el-table-column
          type="index"
          label="序号"
          width="50"
          align="center"
        ></el-table-column>
        <el-table-column
          prop="extractionTaskName"
          label="抽取任务名称"
          align="center"
          show-overflow-tooltip
        ></el-table-column>
        <!-- <el-table-column
          prop="extractionModelName"
          label="抽取类型"
          align="center"
          show-overflow-tooltip
        ></el-table-column> -->
        <el-table-column
          prop="extractionType"
          label="抽取类型"
          align="center"
          show-overflow-tooltip
        >
          <template slot-scope="scope">
            <template v-if="scope.row.extractionType === 1"> 算法 </template>
            <template v-else-if="scope.row.extractionType === 2">
              大模型
            </template>
            <template v-else-if="scope.row.extractionType === 3">
              正则表达式
            </template>
            <template v-else-if="scope.row.extractionType === 4">
              结构化抽取
            </template>
          </template>
        </el-table-column>
        <el-table-column
          prop="contentNumber"
          label="内容数量"
          align="center"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          prop="entityNum"
          label="已抽取实体数量"
          align="center"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          prop="propertyNum"
          label="已抽取属性数量"
          align="center"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          prop="relationNum"
          label="已抽取关系数量"
          align="center"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          prop="status"
          label="状态"
          align="center"
          show-overflow-tooltip
        >
          <template slot-scope="scope">
            <template v-if="scope.row.status === 0">
              <i class="little-circle-info"></i>
              未开始
            </template>
            <template v-else-if="scope.row.status === 1">
              <i class="little-circle-primary"></i>
              进行中
            </template>
            <template v-else-if="scope.row.status === 2">
              <i class="little-circle-warn"></i>
              已暂停
            </template>
            <template v-else-if="scope.row.status === 3">
              <span style="cursor: pointer" @click="showException(scope.row)">
                <i class="little-circle-danger"></i>
                任务异常
              </span>
            </template>
            <template v-else-if="scope.row.status === 4">
              <i class="little-circle-success"></i>
              已完成
            </template>
          </template>
        </el-table-column>
        <el-table-column
          label="操作"
          width="180"
          fixed="right"
          align="center"
          class="operation"
        >
          <template slot-scope="scope">
            <el-link
              v-if="scope.row.status !== 4"
              class="handle-button"
              :underline="false"
              type="primary"
              @click.native.prevent="editTask(scope.row)"
              >编辑</el-link
            >
            <el-link
              v-if="scope.row.status === 4"
              :underline="false"
              class="handle-button"
              type="primary"
              @click.native.prevent="showTaskRes(scope.row)"
            >
              查看
            </el-link>
            <!-- 结构化抽取开启操作在编辑页面执行 -->
            <el-link
              v-if="scope.row.status === 0 && scope.row.extractionType !== 4"
              :underline="false"
              class="handle-button"
              type="primary"
              @click.native.prevent="startTask(scope.row)"
            >
              开启
            </el-link>
            <!-- 结构化抽取不提供暂停操作 -->
            <el-link
              v-if="scope.row.status === 1 && scope.row.extractionType !== 4"
              class="handle-button"
              :underline="false"
              type="primary"
              @click.native.prevent="pauseTask(scope.row)"
              >暂停</el-link
            >
            <!-- 结构化抽取不可暂停 不提供重新开启操作 -->
            <el-link
              v-if="
                (scope.row.status === 3 || scope.row.status === 2) &&
                scope.row.extractionType !== 4
              "
              class="handle-button"
              :underline="false"
              type="primary"
              @click.native.prevent="restartTask(scope.row)"
              >重新开始</el-link
            >
            <el-link
              :underline="false"
              class="handle-button"
              type="primary"
              @click.native.prevent="delTask(scope.row)"
            >
              删除
            </el-link>
          </template>
        </el-table-column>
      </el-table>
      <div class="table-pagination" v-if="total">
        <el-pagination
          background
          layout="total, prev, pager, next,sizes, jumper"
          :total="total"
          :pager-count="5"
          :page-sizes="[10, 20, 30]"
          :current-page.sync="searchParams.page_index"
          :page-size.sync="searchParams.page_size"
          @current-change="handleCurrentChange"
          @size-change="handleSizeChange"
        >
        </el-pagination>
      </div>
    </div>
    <!-- 导入图谱 -->
    <el-dialog title="导入图谱" :visible.sync="dialogFormVisible" width="30%">
      <el-form :model="dialogForm" ref="dialogForm" :rules="dialogRules">
        <el-form-item label="图谱名称:" prop="atlas" class="dialog-inline">
          <el-select
            v-model="dialogForm.atlas"
            style="width: 100%"
            filterable
            placeholder="请选择导入的图谱"
          >
            <el-option
              v-for="item in dialogOptions"
              :key="item.id"
              :label="item.label"
              :value="item.id"
            >
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitDialogForm">确 定</el-button>
      </div>
    </el-dialog>
    <!-- 编辑任务 -->
    <el-dialog
      title="修改抽取任务"
      width="35%"
      @close="afterExtractClose"
      :visible.sync="dialogExtractVisible"
    >
      <el-form
        ref="dialogExtractForm"
        label-position="left"
        label-width="120px"
        :model="extractForm"
        :rules="extractRules"
      >
        <el-form-item label="抽取任务名称：" prop="extractionTaskName">
          <el-input
            v-model="extractForm.extractionTaskName"
            placeholder="请输入任务名称"
          ></el-input>
        </el-form-item>
        <el-form-item label="抽取类型：" prop="extractionType">
          <el-radio-group v-model="extractForm.extractionType">
            <el-radio
              v-for="r in extractTypeOptions"
              :key="r.value"
              :label="r.value"
              :disabled="
                extractForm.status !== 0 ||
                (r.value === 3 && !regexpRadioAble) ||
                (r.value === 4 && !structRadioAble)
              "
              style="margin: 10px"
            >
              {{ r.label }}
              <template v-if="r.value === 3">
                <el-tooltip content="正则表达式抽取仅支持doc/docx/txt文件">
                  <i class="el-icon-warning"></i>
                </el-tooltip>
              </template>
              <template v-if="r.value === 4">
                <el-tooltip
                  content="结构化抽取类型仅支持xls/xlsx/csv格式的单文件"
                >
                  <i class="el-icon-warning"></i>
                </el-tooltip>
              </template>
            </el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item
          label="选择抽取算法："
          prop="extractionModelId"
          v-if="extractForm.extractionType === 1"
        >
          <el-select
            v-model="extractForm.extractionModelId"
            :disabled="extractForm.status !== 0"
            placeholder="请选择"
            filterable
            style="width: 100%"
          >
            <el-option
              v-for="item in extractAlgoList"
              :key="item.id"
              :label="item.modelName"
              :value="item.id"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item
          label="选择抽取模型："
          prop="extractionModelId"
          v-if="extractForm.extractionType === 2"
        >
          <el-select
            v-model="extractForm.extractionModelId"
            :disabled="extractForm.status !== 0"
            placeholder="请选择"
            filterable
            style="width: 100%"
          >
            <el-option
              v-for="item in extractModelList"
              :key="item.id"
              :label="item.modelName"
              :value="item.id"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item
          label="选择抽取规则："
          prop="extractionModelId"
          v-if="extractForm.extractionType === 3"
        >
          <el-select
            v-model="extractForm.extractionModelId"
            :disabled="extractForm.status !== 0"
            placeholder="请选择"
            filterable
            style="width: 100%"
          >
            <el-option
              v-for="item in extractRuleList"
              :key="item.ruleId"
              :label="item.name"
              :value="item.ruleId"
            >
            </el-option>
          </el-select>
        </el-form-item>

        <el-form-item
          label="本体模型："
          prop="ontologyAllId"
          v-if="extractForm.extractionType === 2"
        >
          <el-select
            v-model="extractForm.ontologyAllId"
            :disabled="extractForm.status !== 0"
            placeholder="请选择本体模型"
            filterable
            style="width: 100%"
          >
            <el-option
              v-for="item in ontologyModelList"
              :key="item.id"
              :label="item.title"
              :value="item.id"
            >
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogExtractVisible = false">取消</el-button>
        <el-button type="primary" @click="saveTaskEdit">确定</el-button>
      </div>
    </el-dialog>
    <!-- 任务异常信息 -->
    <el-dialog title="任务异常信息" :visible.sync="dialogVisible" width="35%">
      <div class="task-error-info">
        <i class="el-icon-error"></i>
        <span class="error-content">{{ exceptionRow.exceptionMessage }}</span>
      </div>
    </el-dialog>
  </div>
</template>
<script>
export default {
  name: 'ExtractTask',
  components: {},
  data: () => {
    return {
      searchParams: {
        file_name: null, // 任务名称
        extraction_type: null, // 抽取模型
        status: null, // 融合状态
        page_index: 1, // 页码
        page_size: 10, // 每页条数
      },
      tableList: [], // 数据列表
      total: 0, // 数据总条数
      loading: false,
      selections: [], // 选中项
      extractModels: [], // 抽取模型
      // 状态
      statusOptions: [
        { label: '未开始', value: 0 },
        { label: '进行中', value: 1 },
        { label: '已暂停', value: 2 },
        { label: '任务异常', value: 3 },
        { label: '已完成', value: 4 },
      ],
      // 导入图谱
      dialogFormVisible: false,
      dialogForm: {
        atlas: null,
      },
      dialogOptions: [],
      dialogRules: {
        atlas: [
          {
            required: true,
            message: '请选择图谱',
            trigger: 'blur',
          },
        ],
      },
      // 编辑抽取任务
      extractAlgoList: [], // 抽取算法列表
      extractModelList: [], // 抽取模型列表
      extractRuleList: [], // 抽取规则列表
      dialogExtractVisible: false,
      extractForm: {
        extractionTaskName: null,
        extractionType: 1,
        modelId: null,
        ontologyAllId: null,
        source_file_ids: [],
      },
      extractRules: {
        extractionTaskName: [
          {
            required: true,
            message: '请输入抽取任务名称',
            trigger: 'blur',
          },
        ],
        extractionType: [
          {
            required: true,
            message: '请选择抽取类型',
            trigger: 'blur',
          },
        ],
        extractionModelId: [
          {
            required: true,
            message: '请选择抽取算法/模型/规则',
            trigger: 'blur',
          },
        ],
      },
      extractTypeOptions: [
        { label: '算法', value: 1 },
        { label: '大模型', value: 2 },
        { label: '正则表达式', value: 3 },
        { label: '结构化抽取', value: 4 },
      ],
      exceptionRow: {}, // 任务异常row
      dialogVisible: false,
      ontologyModelList: [], // 本体模型列表
      curExtractRow: null,
    };
  },
  computed: {
    // 结构化抽取是否可选择 条件：单文件 且格式为xls xlsx csv三种之一
    structRadioAble() {
      if (this.extractForm.source_file_ids.length === 1) {
        let fileType = null;
        if (this.curExtractRow) {
          fileType = this.curExtractRow.extractionTaskName
            .split('.')
            .pop()
            .toLowerCase();
        }
        if (['xls', 'xlsx', 'csv'].includes(fileType)) {
          return true;
        }
        return false;
      }
      return false;
    },

    // 正则抽取是否可选择 条件: 格式为doc docx txt三种之一
    regexpRadioAble() {
      if (this.curExtractRow) {
        let fileType = this.curExtractRow.extractionTaskName
          .split('.')
          .pop()
          .toLowerCase();
        if (['doc', 'docx', 'txt'].includes(fileType)) {
          return true;
        }
        return false;
      }
      return false;
    },
  },
  created() {
    this.getPageData();
    this.getModelOptions();
    // 获取抽取模型列表
    this.getExtractModel();
    // 获取抽取规则列表
    this.getExtractRules();
    // 获取图谱列表
    this.getGraphName();
    // 获取实体模型列表
    this.getOntologyModel();
  },
  methods: {
    // 页面数据
    getPageData() {
      this.loading = true;
      this.$api.knowledgeGeneration
        .getExtractTaskList(this.searchParams)
        .then((res) => {
          const { data, message, code } = res.data;
          if (code === 200) {
            this.tableList = data.list.map((item) => {
              if (item.extractionModelId == 12) {
                item.entityNum = 31;
                item.propertyNum = 31;
                item.relationNum = 9;
              }
              return item;
            });
            this.total = data.total;
          } else {
            this.$message.warning(message);
          }
        })
        .catch((err) => {
          console.log(err);
        })
        .finally(() => {
          this.loading = false;
        });
    },
    // 获取本体模型下拉框数据
    async getModelOptions() {
      let res = await this.$api.knowledgeGeneration.getExtractModel();
      if (res.data.code !== 200) {
        this.$message.warning(res.data.message);
        return;
      }
      // this.extractModels = res.data.data;
    },
    // 获取算法和模型数据 modelType值 1：算法 2：模型
    getExtractModel() {
      this.$api.knowledgeGeneration.getExtractModel().then((res) => {
        const { code, data, message } = res.data;
        if (code !== 200) {
          console.error(res);
          this.$message.error(message);
          return;
        }
        this.extractAlgoList = data.filter((e) => e.modelType === 1);
        this.extractModelList = data.filter((e) => e.modelType === 2);
      });
    },
    // 获取抽取规则
    getExtractRules() {
      this.$api.knowledgeGeneration
        .getAllEnableExtractRule()
        .then((res) => {
          const { data, message, code } = res.data;
          if (code === 200) {
            this.extractRuleList = data;
          } else {
            this.$message.warning(message);
          }
        })
        .catch((err) => {
          console.log(err);
        });
    },
    // 获取图谱列表
    async getGraphName() {
      let res = await this.$api.knowledgeGeneration.chooseGraph();
      if (res.data.code !== 200) {
        this.$message.warning(res.data.message);
        return;
      }
      this.dialogOptions = res.data.data.map((item) => {
        const { graphId: id, graphName: label } = item;
        return {
          id,
          label,
        };
      });
    },
    getOntologyModel() {
      this.$api.knowledgeGeneration.getOntologyModel().then((res) => {
        const { code, data, message } = res.data;
        if (code !== 200) {
          console.error(res);
          this.$message.error(message);
          return;
        }
        this.ontologyModelList = data.map((ontologyModel) => ({
          id: ontologyModel.ontologyAllId,
          title: ontologyModel.ontologyAllName,
        }));
      });
    },
    // 查询
    searchData() {
      this.getPageData();
    },
    // 选中数据
    handleSelectionChange(selection) {
      this.selections = selection;
    },
    // 创建任务
    createTask() {},
    // 导入图谱
    importGraph() {
      if (!this.selections.length) {
        return this.$message.warning('请先选择要操作的数据项');
      }
      this.dialogFormVisible = true;
    },
    submitDialogForm() {
      this.$refs.dialogForm.validate((valid) => {
        if (valid) {
          this.dialogFormVisible = false;
          const loading = this.$message({
            showClose: true,
            dangerouslyUseHTMLString: true,
            duration: 0,
            customClass: 'el-message-loading',
            message: `<div class="el-loading-spinner">
                        <svg viewBox="25 25 50 50" class="circular">
                          <circle cx="50" cy="50" r="15" fill="none" class="path">
                          </circle>
                        </svg>
                      </div>
                      <span class="el-message-loading__text">
                        正在导入图谱,请稍候......
                      </span>`,
          });
          this.dialogFormVisible = false;

          this.$api.knowledgeGeneration
            .importExtractData({
              graphId: this.dialogForm.atlas,
              extractionDataRecordId: this.selections
                .map((i) => i.id)
                .join(','),
            })
            .then((res) => {
              const { code, message, data } = res.data;
              if (code !== 200) {
                this.$message.warning(message);
                return;
              }
              this.$message.success(message);
              if (data?.targetUrl == 'entityLink') {
                setTimeout(
                  () =>
                    this.$router.push('/knowledgeGeneration/entityLink/index'),
                  1000
                );
              }
            })
            .catch((err) => {
              console.log(err);
              this.$message.warning(err.data.message);
            })
            .finally(() => {
              loading.close();
            });
        } else {
          return false;
        }
      });
    },
    // 显示异常信息
    showException(row) {
      this.exceptionRow = row;
      this.dialogVisible = true;
    },
    // 编辑
    editTask(row) {
      // 抽取类型为结构化抽取时 跳转页面
      // 其他类型打开弹窗
      if (row.extractionType === 4) {
        this.$router.push({
          path: '/knowledgeGeneration/extractTask/struct',
          query: {
            name: row.extractionTaskName,
            fileName: row.fileName,
            id: row.childId,
            fileId: row.fileId,
          },
        });
      } else {
        this.extractForm = Object.assign({}, row);
        this.curExtractRow = row;
        this.extractForm.source_file_ids = [row.id];
        console.log('curExtractRow', this.curExtractRow);
        this.dialogExtractVisible = true;
      }
    },
    // 编辑弹窗关闭后
    afterExtractClose() {
      this.extractForm = {
        extractionTaskName: null,
        extractionType: 1,
        modelId: null,
        ontologyAllId: null,
        source_file_ids: [],
      };
      this.curExtractRow = null;
      this.$refs.dialogExtractForm.clearValidate();
    },
    // 保存任务修改
    saveTaskEdit() {
      // 只提交可能变化的项
      let modelName;
      if (this.extractForm.extractionType === 1) {
        modelName = this.extractAlgoList.find(
          (i) => i.id === this.extractForm.extractionModelId
        )?.modelName;
      } else if (this.extractForm.extractionType === 2) {
        modelName = this.extractModelList.find(
          (i) => i.id === this.extractForm.extractionModelId
        )?.modelName;
      } else if (this.extractForm.extractionType === 3) {
        modelName = this.extractRuleList.find(
          (i) => i.ruleId === this.extractForm.extractionModelId
        )?.name;
      }
      if (!modelName) {
        return this.$message.warning('未获取到算法/模型/规则名');
      }
      console.log('this.extractForm', this.extractForm);
      this.$api.knowledgeGeneration
        .updateExtractTask({
          id: this.extractForm.id,
          extractionTaskName: this.extractForm.extractionTaskName,
          extractionType: this.extractForm.extractionType,
          ontologyAllId: this.extractForm.ontologyAllId,
          extractionModelId: this.extractForm.extractionModelId,
          extractionModelName: modelName,
        })
        .then((res) => {
          const { data, message, code } = res.data;
          if (code === 200) {
            this.$message.success(message);
            this.dialogExtractVisible = false;
            this.getPageData();
          } else {
            this.$message.warning(message);
          }
        })
        .catch((err) => {
          console.log(err);
        });
    },
    // 开启
    startTask(row) {
      this.$api.knowledgeGeneration
        .startExtractTask({ id: row.id })
        .then((res) => {
          const { message, code } = res.data;
          if (code === 200) {
            this.getPageData();
            this.$message.success(message);
          } else {
            this.$message.warning(message);
          }
        })
        .catch((err) => {
          console.log(err);
        });
    },
    // 重新开始
    restartTask(row) {
      this.startTask(row);
    },
    pauseTask(row) {
      if (row.extractionType === 4) {
        return this.$message.warning('结构化抽取任务无法中止！');
      }
      this.$api.knowledgeGeneration
        .pauseExtractTask({ id: row.id })
        .then((res) => {
          const { message, code } = res.data;
          if (code === 200) {
            this.getPageData();
            this.$message.success(message);
          } else {
            this.$message.warning(message);
          }
        })
        .catch((err) => {
          console.log(err);
        });
    },
    // 删除
    delTask(row) {
      this.$confirm('此操作将删除此数据，是否继续？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        this.$api.knowledgeGeneration
          .delExtractTask({ id: row.id })
          .then((res) => {
            const { data, message, code } = res.data;
            if (code === 200) {
              this.getPageData();
              this.$message.success(message);
            } else {
              this.$message.warning(message);
            }
          })
          .catch((err) => {
            console.log(err);
          });
      });
    },
    // 查看数据
    showTaskRes(row) {
      // 结构化抽取直接跳转数据查看页面
      // 0928 增加MBTX实体抽取modelId=12 直接跳转二级查看页面
      if (row.extractionType === 4 || row.extractionModelId == '12') {
        this.$router.push({
          path: `/knowledgeGeneration/extract/detail/${row.childId}`,
          query: {
            type: row.extractionType,
            fileId: row.fileId,
            modelId: row.extractionModelId,
          },
        });
      } else {
        this.$router.push({
          path: '/knowledgeGeneration/extract/index',
          query: { id: row.id, type: row.extractionType },
        });
      }
    },
    handleCurrentChange() {
      this.getPageData();
    },
    handleSizeChange() {
      this.getPageData();
    },
  },
};
</script>

<style lang="scss" scoped>
.task-error-info {
  padding: 8px 16px;
  max-height: 500px;
  color: #f56c6c;
  overflow-y: auto;
  background-color: #fef0f0;
  .el-icon-error {
    font-size: 20px;
  }
}
</style>
